package com.gzsxy.sso.core.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gzsxy.sso.common.dto.request.MenuRequest;
import com.gzsxy.sso.common.dto.response.MenuRsp;

import com.gzsxy.sso.common.exception.impl.BusinessException;
import com.gzsxy.sso.common.exception.impl.CustomAssert;
import com.gzsxy.sso.common.result.ResultCodeEnum;
import com.gzsxy.sso.core.dao.AppMapper;
import com.gzsxy.sso.core.dao.FunctionMapper;
import com.gzsxy.sso.core.dao.MenuMapper;
import com.gzsxy.sso.core.entity.Menu;
import com.gzsxy.sso.core.entity.vo.MenuQueryVo;
import com.gzsxy.sso.core.model.SessionUser;
import com.gzsxy.sso.core.service.MenuService;
import com.gzsxy.sso.core.service.UserService;
import com.gzsxy.sso.core.utils.SessionUserUtil;
import com.gzsxy.sso.core.utils.TreeUtil;
import com.gzsxy.sso.core.utils.ValidateUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author xiaolong
 * @version 1.0
 * @description: 菜单
 * @date 2021/11/18 11:17
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {

    @Autowired
    private UserService userService;

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private AppMapper appMapper;

    @Autowired
    private FunctionMapper functionMapper;



    /**
     * @description: 获取用户拥有的菜单权限
     * @param
     * @return
     */
    @Override
    public List<MenuRsp> getUserMenu(MenuQueryVo menuQueryVo) {

        boolean isSadmin;
        //用户id为空
        if (StringUtils.isEmpty(menuQueryVo.getUserId())){
            //查询当前登录用户
            SessionUser loginUser = SessionUserUtil.getSessionUser();
            menuQueryVo.setUserId(loginUser.getId());
            //查询当前用户是否为超级管理员
            isSadmin = loginUser.getIsSadmin();
        } else {
            //获取用户拥有的菜单权限
            isSadmin = userService.isSadmin(menuQueryVo.getUserId());
        }
        List<MenuRsp> list;
        if (isSadmin){
            //超级管理员获取所有的菜单权限
            list = menuMapper.findByApp(menuQueryVo);
        } else {
            //获取用户拥有的菜单权限
            list = menuMapper.findMenuByUserId(menuQueryVo);
        }
        //获取树结构  Comparator.comparing(MenuRsp::getOrderId).reversed() 按照List中对象的getOrderId属性降序
        List<MenuRsp> build = TreeUtil.build(list, Comparator.comparing(MenuRsp::getOrderId).reversed());
        //过滤获取的树列表中一级菜单含有level==1的或者level==2的，
        // 因为有些一级菜单没有绑定功能所以没有查询出来，程序把二级菜单当作一级菜单返回
        List<MenuRsp> collect = build.stream().filter(menuRsp -> {
            return menuRsp.getLevel() == 0;
        }).collect(Collectors.toList());
        return collect;
    }


    /**
     * @description: 获取全部菜单功能
     * @param
     * @return
     */
    @Override
    public List<MenuRsp> getMenu(MenuQueryVo menuQueryVo) {
        List<MenuRsp> list = menuMapper.getMenu(menuQueryVo);
        //获取树结构  Comparator.comparing(MenuRsp::getOrderId).reversed() 按照List中对象的getOrderId属性降序
        return TreeUtil.build(list,Comparator.comparing(MenuRsp::getOrderId).reversed());
    }


    /**
     * @description: 根据角色id查询所有功能列表
     * @param
     * @return
     */
    @Override
    public List<MenuRsp> getfunctionByRoles(String roleId) {

        List<MenuRsp>  list = menuMapper.getfunctionByRoles(roleId);
        //获取树结构  Comparator.comparing(MenuRsp::getOrderId).reversed() 按照List中对象的getOrderId属性降序
        return TreeUtil.build(list,Comparator.comparing(MenuRsp::getOrderId).reversed());
    }


    /**
     * @description: 添加菜单
     * @param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addMenu(MenuRequest menuRequest) {
        //校验appId是否不存在
        ValidateUtil.isExist(appMapper,menuRequest.getAppId(), ResultCodeEnum.APP_NOT_FOUND.getMessage());
        //菜单名称唯一性校验
        ValidateUtil.assertUnique(menuMapper::existByMenuName,menuRequest.getAppId(),menuRequest.getName(),ResultCodeEnum.MENU_NAME_EXIST.getMessage());
        //校验功能
        if (StringUtils.isNotEmpty(menuRequest.getFuncId())){
            ValidateUtil.isExist(functionMapper,menuRequest.getFuncId(),ResultCodeEnum.FUNCTION_NOT_FOUND.getMessage());
        }
        Menu menu = new Menu();
        BeanUtils.copyProperties(menuRequest,menu);
        //设置代码
        menu.setCode(com.gzsxy.sso.common.utils.StringUtils.getPinYinHeadChar(menuRequest.getName()));
        baseMapper.insert(menu);
    }


    /**
     * @description: 编辑菜单
     * @param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateMenu(MenuRequest menuRequest) {
        Menu menu = baseMapper.selectById(menuRequest.getId());
        //菜单不存在或已删除
        CustomAssert.notTrue(ObjectUtils.isNotEmpty(menu),ResultCodeEnum.MENU_NOT_FOUND.getMessage(),ResultCodeEnum.MENU_NOT_FOUND.getCode());
        Menu menu1 = new Menu();
        BeanUtils.copyProperties(menuRequest,menu1);
        //修改了菜单名
        if (!menu.getName().equals(menuRequest.getName())){
            //菜单名称唯一性校验
            ValidateUtil.assertUnique(menuMapper::existByMenuName,menuRequest.getAppId(),menuRequest.getName(),ResultCodeEnum.MENU_NAME_EXIST.getMessage());
            String pinYinHeadChar = com.gzsxy.sso.common.utils.StringUtils.getPinYinHeadChar(menuRequest.getName());
            menu1.setCode(pinYinHeadChar);
        }
        //如果功能id不为空，并且功能id修改了
        if (StringUtils.isNotEmpty(menuRequest.getFuncId()) && !menuRequest.getFuncId().equals(menu.getFuncId())){
            //功能名不存在或已删除
            ValidateUtil.isExist(functionMapper,menuRequest.getFuncId(),ResultCodeEnum.FUNCTION_NOT_FOUND.getMessage());
        }
//        SessionUser sessionUser = SessionUserUtil.getSessionUser();
//        menu1.setUpdateUser(sessionUser.getUserName());
        baseMapper.updateById(menu1);
    }


    /**
     * @description: 根据id查询菜单
     * @param
     * @return
     */
    @Override
    public Menu selectById(String menuId) {
        return  baseMapper.selectById(menuId);
    }


    /**
     * @description: 删除菜单
     * @param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteMenu(String menuId, Boolean isConform) {
        Menu menu = baseMapper.selectById(menuId);
        //菜单不存在或已删除
        CustomAssert.notTrue(ObjectUtils.isNotEmpty(menu),ResultCodeEnum.MENU_NOT_FOUND.getMessage(),ResultCodeEnum.MENU_NOT_FOUND.getCode());
        List<String> deleteList = new ArrayList<>();
        deleteList.add(menuId);
        //存在子菜单
        if (baseMapper.existChildren(menuId)){
            if (!isConform){
                //删除失败，请先删除子菜单
                throw new BusinessException(ResultCodeEnum.MENU_DELETE_FAILED_EXIST_CHILDREN.getMessage());
            }
            //查询子菜单
            List<MenuRsp> list = baseMapper.findChildren(menuId);
            //获取子菜单id集合
            List<String> idList = list.stream().map(MenuRsp::getId).collect(Collectors.toList());
            deleteList.addAll(idList);
        }
        //批量删除
        baseMapper.deleteBatchIds(deleteList);

    }
}
